/*
	Pinkie's Balloon Fight
	Copyright (C) 2012  dancinninja (dancinninjac@gmail.com)

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "Init.h"
#include <vector>
#include "LiveObject.h"
#include "Player.h"
#include "Platform.h"
#include "Enemy.h"
#include "TexManager.h"

// TODO: 
//x		platforms
//x		collision detection
//		baddies
//x		lives
//		A struct to hold all the variables necessary to make a platform
//			- This will then be later populated from a file

//-----------------------------------------------------------------

bool LoadLevelTextures(int level = 0);
bool GameInit();
void GameLoop();
void GameExit();

//-----------------------------------------------------------------

float zoom = -15.0f;      // Distance from the stage

// TODO: make this dynamic?
Player* player;

// TODO: Definitely make this dynamic!
static const int NUM_OF_PLATFORMS = 4;
Platform platform[NUM_OF_PLATFORMS];
static int NUM_OF_ENEMIES = 4;
//Question: We will never have that many enemies on one screen.
// Would it be better to use a simple array (speed)
// than a linked list?
//Answer: Linked list, since I'll have different types of enemies.
std::vector<Enemy*> enemy;

// Our texture manager will stay with us
TexManager texmanager;

//---------------------------------------------
//---------------------------------------------
//---------------------------------------------
//---------------------------------------------
//---------------------------------------------
//---------------------------------------------


void GameLoop(){
	
	//TODO: Update the enemy vector to eliminate dead enemies!

	// Movement
	player->Update();

	for(int i = 0; i < NUM_OF_ENEMIES; i++){
		enemy[i]->Update();
	}

	// Collision detection (MAKE INTO QUADTREE?)
	// Loop through platforms
	for(int i = 0; i < NUM_OF_PLATFORMS; i++){
		// Let's try a radical way of thinking: 
		// If we've hit one, we probably haven't hit another!
		if(player->CollideWithPlatform(platform[i])) break;
	}
	// Loop through Enemies
	for(int i = 0; i < NUM_OF_ENEMIES; i++){
		player->CollideWithEnemy(enemy[i]);
	}

	// Check enemies against the platforms
	// TODO: and each other!
	for(int e = 0; e < NUM_OF_ENEMIES; e++){
		for(int p = 0; p < NUM_OF_PLATFORMS; p++){
			if(enemy[e]->CollideWithPlatform(platform[p])) break;
		}
	}

	// Display	
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);


	// Render the platforms now:
	for(int i = 0; i < NUM_OF_PLATFORMS; i++){
		platform[i].Render();
	}
	// Render the platforms now:
	for(int i = 0; i < NUM_OF_ENEMIES; i++){
		enemy[i]->Render();
	}

	// And finally, the player:
	player->Render();

}


bool GameInit(){
	// Set up the graphics:
	glEnable(GL_TEXTURE_2D);
	glShadeModel(GL_SMOOTH);
	glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
	glClearDepth(1.0f);
	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
	glBlendFunc(GL_SRC_ALPHA,GL_ONE);
	glEnable(GL_BLEND);

	// Generate the player
	player = new Player();
	// Starting position 
	// (Temporary? Make it in the same place every time? Which one?)
	player->SetPosition(40, 400);

	// Load the platforms
	//TODO: load this from a file!
	platform[0].SetPosition(300, 400);
	platform[1].SetPosition(300, 200);
	platform[2].SetPosition(100, 100);
	platform[3].SetPosition(000, 000);

	// Load the Enemies
	//TODO: load this from a file!

	// We will never need more than this per level
	enemy.reserve(NUM_OF_ENEMIES);
	for(int i = 0; i < NUM_OF_ENEMIES; i++){
		Enemy* tempEnemy = new Enemy();
		enemy.push_back(tempEnemy);
	}
	enemy[0]->SetPosition(300, 450);
	enemy[1]->SetPosition(200, 250);
	enemy[2]->SetPosition(100, 150);
	enemy[3]->SetPosition(000, 550);

	if (!LoadLevelTextures()){
		return false;
	}
	return true;
}

// Clean up all the trash that we made in the main game loop
void GameExit(){
	
	delete player;

}



int WINAPI WinMain(	HINSTANCE	hInstance,
					HINSTANCE	hPrevInstance,	
					LPSTR		lpCmdLine,
					int			nCmdShow){		

	MSG		msg;
	BOOL	done = FALSE;

	// Ask The User Which Screen Mode They Prefer
	//if (MessageBox(NULL,"Would You Like To Run In Fullscreen Mode?", "Start FullScreen?",MB_YESNO|MB_ICONQUESTION)==IDNO)
	{
		fullscreen=FALSE;							// Windowed Mode
	}

	// Create Our Window
	if (!CreateTheWindow("Pinkie",640,480,16,fullscreen)){
		return 0;									// Quit If Window Was Not Created
	}

	while(!done){									// Loop That Runs While done=FALSE
		if (PeekMessage(&msg,NULL,0,0,PM_REMOVE)){	// Is There A Message Waiting?	
			if (msg.message==WM_QUIT){				// Have We Received A Quit Message?
				done = TRUE;						// If So done = TRUE
			}else{									// If Not, Deal With Window Messages
				TranslateMessage(&msg);				// Translate The Message
				DispatchMessage(&msg);				// Dispatch The Message
			}
		}else{
			// Run the game loop

			GameLoop();
			// Draw The Scene.  Watch For ESC Key And Quit Messages From GameLoop()
			if (keys[VK_ESCAPE]){	
				done = TRUE;						// ESC or GameLoop Signalled A Quit
			}
			else{									// Not Time To Quit, Update Screen
			
				SwapBuffers(hDC);					// Swap Buffers (Double Buffering)

				if (keys[VK_UP]){
					//Replace with "If pressed don't do it again" thing:
					//if(player->flapCountdown < 10){
						//player->flapCountdown = 10;

					if(player->IsReadyToJump()){
						// Change it to nothing first, then check for directions
						DIRECTION dir = NONE;

						if (keys[VK_LEFT]){
							dir = LEFT;
						}
						else if (keys[VK_RIGHT]){
							dir = RIGHT;				
						}
						player->ChangeDirection(dir);
						player->Jump();
						
					}
				}
				// We released the jump button, so we can jump again.
				if (!keys[VK_UP]){
					player->SetReadyToJump();
				}

			}
		}
	}

	// Shutdown
	KillWindow();									// Kill The Window
	return (msg.wParam);							// Exit The Program
}

/////////////////////////////////////////////////////////////////////////////////////////

bool LoadLevelTextures(int level){

	bool status = false;

	// Allocate the number of textures we will be using
	//TODO: make this dynamic for each level
	texmanager.Reserve(2);

	if(texmanager.LoadTexture("data/Pinkie.bmp") &&
		texmanager.LoadTexture("data/Balloon.bmp")){

		player->SetTexture(texmanager.GetTexture(0));
		for(int i = 0, playerLives = player->GetLives(); i < playerLives; ++i){
			player->balloons[i].SetTexture(texmanager.GetTexture(1));
		}
		status = true;
	}

	return status;
}



 
